/* Copyright (c) 2019, Guillaume Champagne
 * All rights reserved.
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 */

#ifndef CONFIG_H_
#define CONFIG_H_

#define _GNU_SOURCE 1

#include <stdio.h>
#include <sched.h>
#include <pthread.h>
#include <mqueue.h>
#include <semaphore.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>
#include <signal.h>
#include <errno.h>

#include <unistd.h>
#include <sys/types.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

/**
 * Parameters
 */

#ifndef BASE_PRIO
#define BASE_PRIO 30
#endif

#ifndef LITE_PRIO
#define LITE_PRIO 31
#endif

#ifndef USER_SIGNAL
#define USER_SIGNAL SIGUSR1
#endif

/**
 * Type definitions
 */
typedef void* no_task_retval_t;
typedef void* no_task_argument_t;
typedef int no_main_retval_t;
typedef int no_main_argument_t;
typedef no_task_retval_t (*no_task_entry_t)(no_task_argument_t);
typedef pthread_t no_task_handle_t;
typedef struct timespec no_time_t;
typedef sem_t no_sem_t;
typedef pthread_mutex_t no_mutex_t;
typedef pthread_cond_t no_event_t;
typedef mqd_t no_mq_t;
typedef void (*no_int_handler_t)(int, void*);

/**
 * Macros
 */
#define INITIALIZATION_TASK_RETVAL int
#define INITIALIZATION_TASK_ARG void
#define INITIALIZATION_TASK_NAME main

#define TASK_DEFAULT_RETURN NULL
#define MAIN_DEFAULT_RETURN 0

#define NO_INIT_MAX_TIME_VALUE 0x7FFFFFFF

#ifndef TRACING
#ifndef NO_VERBOSE_RESULTS
#define REPORT_BENCHMARK_RESULTS(STR_PTR) do { \
			no_serial_write(STR_PTR); \
			no_result_report(max_cycles, min_cycles, average_cycles); \
			fflush(stdout); \
		} while (0);
#else
#define REPORT_BENCHMARK_RESULTS(STR_PTR) do { \
			for (int _i; _i < NB_ITER; _i++) { \
				no_single_result_report("", no_cycles_results[_i]); \
			} \
		} while (0);
#endif
#endif

#define BITSPERLONG 32
#define TOP2BITS(x) ((x & (3L << (BITSPERLONG-2))) >> (BITSPERLONG-2))

#define DO_WORKLOAD(i) \
	do { \
		unsigned long x = 9; \
		unsigned long a = 0L; \
		unsigned long r = 0L; \
		unsigned long e = 0L; \
		int _workload_i_; \
		for (_workload_i_ = 0; _workload_i_ < BITSPERLONG; _workload_i_++) \
		{ \
			r = (r << 2) + TOP2BITS(x); x <<= 2; \
			a <<= 1; \
			e = (a << 1) + 1; \
			if (r >= e) \
			{ \
				r -= e; \
				a++; \
			} \
		} \
		_workload_results[i] = a; \
	} while (0);

#endif
